<template>
 <div class="goc-editor" :style="{ width: computedWidth, height: computedHeight }">
    <!-- 工具栏 -->
    <div class="toolbar">
      <button @click="clear" :disabled="isRunning">清空</button>
      <button @click="toggleAxis" :disabled="isRunning">{{ showAxis ? '隐藏坐标' : '显示坐标' }}</button>
      <button @click="centerView" :disabled="isRunning">居中显示</button>
      <button @click="togglePen" :disabled="isRunning">{{ penVisible ? '隐藏笔' : '显示笔' }}</button>
      <select v-model="currentSpeed" @change="setSpeed" :disabled="isRunning">
        <option value="1">速度1</option>
        <option value="3">速度3</option>
        <option value="5">速度5</option>
        <option value="7">速度7</option>
        <option value="10">速度10</option>
      </select>
    </div>

    <!-- 编辑器区域 -->
    <div class="editor-container">
      <!-- 画布区域 -->
      <div class="canvas-area">
        <div class="canvas-scroll-container">
          <div class="canvas-wrap">
            <canvas ref="axisCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
            <canvas ref="drawCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
            <canvas ref="penCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
          </div>
        </div>
      </div>

      <!-- Monaco 编辑器 -->
      <div class="monaco-area">
        <!-- 编辑器控制按钮 -->
        <div class="editor-controls">
          <button @click="() => run()" :disabled="isRunning" class="run-btn">运行</button>
          <button @click="stop" :disabled="!isRunning" class="stop-btn">停止</button>
          <!-- 字体大小控制按钮 -->
          <div class="font-controls">
            <button @click="decreaseFontSize" class="font-btn" title="减小字体" :disabled="isRunning || fontSize <= MIN_FONT_SIZE">-</button>
            <button @click="increaseFontSize" class="font-btn" title="增大字体" :disabled="isRunning || fontSize >= MAX_FONT_SIZE">+</button>
          </div>
        </div>
        <div ref="editorContainer" class="monaco-container"></div>
      </div>

    </div>

    <!-- 命令面板 - 移到编辑器外面 -->
    <div 
      ref="commandPanelRef"
      class="command-panel" 
      :class="{ 'command-panel-collapsed': !showCommandPanel }"
      :style="commandPanelStyle"
    >
      <div class="command-toggle">
        <button 
          ref="toggleBtnRef"
          class="toggle-btn" 
          @click="handleToggleBtnClick" 
          @mousedown="handleToggleBtnMouseDown"
          :disabled="isRunning" 
          :title="showCommandPanel ? '隐藏命令表' : '点击展开GOC命令表'"
        >
          <span class="toggle-icon">{{ showCommandPanel ? '◀' : '▶' }}</span>
          <span v-if="showCommandPanel" class="toggle-text">命令表</span>
        </button>
      </div>
      
      <div v-if="showCommandPanel" class="command-content">
        <h4>TOC命令表</h4>

        <!-- 颜色选择器面板 - 独立区域 -->
        <div class="color-panel">
          <h5>颜色</h5>
          <div class="color-palette">
            <div 
              v-for="(colorInfo, colorNum) in colorMap" 
              :key="colorNum"
              class="color-item"
              :style="{ backgroundColor: colorInfo.color }"
              :title="`${colorNum}: ${colorInfo.name}`"
              @click.stop="insertColorNumber(colorNum)"
            >
              {{ colorNum }}
            </div>
          </div>
        </div>
        
        <!-- 命令表格 -->
        <table class="command-table">
          <thead>
            <tr>
              <th>命令</th>
              <th>功能</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td @click.stop="insertCommand('pen')" :class="{ 'disabled': isCommandDisabled }">pen</td>
              <td>画笔对象</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand(';')" :class="{ 'disabled': isCommandDisabled }">;</td>
              <td>句尾</td>
            </tr>
            <!-- 基础移动 -->
            <tr>
              <th>基础移动 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.fd(100)')" :class="{ 'disabled': isCommandDisabled }">.fd()</td>
              <td>前进</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.bk(100)')" :class="{ 'disabled': isCommandDisabled }">.bk()</td>
              <td>后退</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.rt(90)')" :class="{ 'disabled': isCommandDisabled }">.rt()</td>
              <td>右转</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.lt(90)')" :class="{ 'disabled': isCommandDisabled }">.lt()</td>
              <td>左转</td>
            </tr>

            <!-- 画笔控制 -->
            <tr>
              <th>画笔控制 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.up()')" :class="{ 'disabled': isCommandDisabled }">.up()</td>
              <td>抬起画笔</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.down()')" :class="{ 'disabled': isCommandDisabled }">.down()</td>
              <td>放下画笔</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.size()')" :class="{ 'disabled': isCommandDisabled }">.size()</td>
              <td>线宽</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.c()')" :class="{ 'disabled': isCommandDisabled }">.c()</td>
              <td>颜色</td>
            </tr>

            <!-- 图形绘制 -->
            <tr>
              <th>图形绘制 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.o(,)')">.o(,)</td>
              <td>圆形</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.oo(,)')">.oo(,)</td>
              <td>实心圆</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.e(,,)')">.e(,,)</td>
              <td>椭圆</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.ee(,,)')">.ee(,,)</td>
              <td>实心椭圆</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.r(,,)')">.r(,,)</td>
              <td>长方形</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.rr(,,)')">.rr(,,)</td>
              <td>实长方形</td>
            </tr>

            <!-- 系统命令 -->
            <tr>
              <th>系统命令 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.cls()')" :class="{ 'disabled': isCommandDisabled }">.cls()</td>
              <td>清屏</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.speed(5)')" :class="{ 'disabled': isCommandDisabled }">.speed()</td>
              <td>执行速度</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.show()')" :class="{ 'disabled': isCommandDisabled }">.show()</td>
              <td>显示画笔</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.hide()')" :class="{ 'disabled': isCommandDisabled }">.hide()</td>
              <td>隐藏画笔</td>
            </tr>

            <!-- 文本 -->
            <tr>
              <th>文本 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.text(,,)')">.text(,,)</td>
              <td>输出文本</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.textSize()')">.textSize()</td>
              <td>文字大小</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.font()')">.font()</td>
              <td>字体</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.setprecision()')">.setprecision()</td>
              <td>数字精度</td>
            </tr>

            <!-- 控制结构 -->
            <tr>
              <th>控制结构 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('for(int i= ; i< ; i++) ')">for循环</td>
              <td>循环结构</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('if() ')">if条件</td>
              <td>条件结构</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('wait()')">wait()</td>
              <td>等待毫秒</td>
            </tr>

            <!-- 输入输出 -->
            <tr>
              <th>输入输出 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('cin >> ;')">cin >></td>
              <td>输入</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('cinWin();')">cinWin()</td>
              <td>窗口输入</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('cout &lt;&lt; ;')">cout &lt;&lt;</td>
              <td>窗口输出</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('cout &lt;&lt; endl;')">cout &lt;&lt; endl</td>
              <td>输出换行</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('cout &lt;&lt; setprecision();')">cout &lt;&lt; setprecision</td>
              <td>设置精度</td>
            </tr>


            <!-- 高级命令 -->
            <tr>
              <th>高级命令 </th>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.moveTo(,)')">.moveTo()</td>
              <td>移动画笔</td>
            </tr>
            <tr>
              <td @click.stop="insertCommand('.lineTo(,)')">.lineTo()</td>
              <td>连线</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 输入输出框 -->
    <div class="io-panel">
      <div class="io-box">
        <label class="io-label">cinWin</label>
        <div class="io-input-container">
          <input 
            ref="cinInput" 
            v-model="cinValue" 
            @keydown.enter="handleCinEnter"
            @keydown.escape="handleCinEscape"
            class="io-input"
            :class="{ 'waiting-for-input': isWaitingForInput }"
            :placeholder="inputMode === 'window' ? '输入数据（多个数据用空格分隔，如：100 50）' : '输入数据...'"
            :disabled="inputMode === 'pen' && !isWaitingForInput"
          />
          <div v-if="inputMode === 'window'" class="input-hint">
            窗口输入模式：在此输入数据，多个数据用空格分隔
          </div>
        </div>
      </div>
      
      <div class="io-box">
        <label class="io-label">coutWin</label>
        <div class="io-output-container">
          <div ref="coutOutput" class="io-output">{{ coutValue }}</div>
        </div>
      </div>
    </div>

    <!-- 笔附近输入框 -->
    <div 
      v-if="showPenInput" 
      class="pen-input-overlay"
      :style="penInputStyle"
    >
      <div class="pen-input-box">
        <input 
          ref="penInput" 
          v-model="penInputValue" 
          @keydown.enter="handlePenInputEnter"
          @keydown.escape="handlePenInputEscape"
          class="pen-input"
          placeholder="输入..."
          autofocus
        />
      </div>
    </div>

    <!-- 成功提示 - 在画布上显示 -->
    <div v-if="showSuccessNotification" class="success-notification">
      <div class="success-content">
        <div class="success-icon">✓</div>
        <div class="success-text">代码运行完成</div>
      </div>
    </div>

    <!-- 错误提示 - 固定在屏幕顶部显示 -->
    <div v-if="errorMessage" class="error-notification">
      <div class="error-content">
        <div class="error-icon">✗</div>
        <div class="error-details">
          <div class="error-text">{{ errorMessage }}</div>
          <div v-if="errorSuggestion" class="error-suggestion">{{ errorSuggestion }}</div>
        </div>
        <button class="error-close-btn" @click="clearError" title="关闭错误提示">×</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, shallowRef, onMounted, onUnmounted, watch, nextTick, computed } from 'vue'
import { tokenize } from '../utils/goc-tokenizer.js'
import { parse } from '../utils/goc-parser.js'
import { execute } from '../utils/goc-interpreter.js'
import gocLanguage from '../utils/goc-language.js'
import TraceCollector from '../utils/goc-trace-collector.js'
import GocErrorHandler from '../utils/goc-error-handler.js'
import GocPerformance from '../utils/goc-performance.js'
import { createSafeResizeObserver, createDebouncedLayoutAdjuster } from '../utils/resize-observer-fix.js'
import logger from '../utils/logger.js'
import commandPanelManager from '../utils/command-panel-manager.js'

// Props
const props = defineProps({
  value: {
    type: String,
    default: `int main() {
    // 在这里编写你的代码

    return 0;
}`
  },
  readOnly: {
    type: Boolean,
    default: false
  },
  theme: {
    type: String,
    default: 'vs-dark'
  },
  width: {
    type: [Number, String],
    default: 1000
  },
  height: {
    type: [Number, String],
    default: 600
  },
  showAxisDefault: {
    type: Boolean,
    default: false
  },
  defaults: {
    type: Object,
    default: () => ({
      speed: 5,
      lineWidth: 1,
      colorIndex: 4
    })
  },
  traceEnabled: {
    type: Boolean,
    default: false
  }
})
// 规范化尺寸，支持数字(px)或百分比等字符串
const normalizeSize = (v) => {
  if (typeof v === 'number') return `${v}px`
  if (typeof v === 'string') {
    const val = v.trim()
    if (val.endsWith('%') || val.endsWith('px') || val.endsWith('vh') || val.endsWith('vw') || val.endsWith('rem') || val.endsWith('em')) return val
    const num = Number(val)
    if (Number.isFinite(num)) return `${num}px`
  }
  return '0px'
}

const computedWidth = normalizeSize(props.width)
const computedHeight = normalizeSize(props.height)

// Emits
const emit = defineEmits(['update:value', 'run-start', 'run-end', 'error', 'trace'])

// Refs
const editorContainer = ref(null)
const axisCanvas = ref(null)
const drawCanvas = ref(null)
const penCanvas = ref(null)
const cinInput = ref(null)
const coutOutput = ref(null)
const penInput = ref(null)
const toggleBtnRef = ref(null)
const commandPanelRef = ref(null)

// 状态 - 使用 shallowRef 避免深度响应式追踪
const editor = shallowRef(null)
const isRunning = ref(false)
const showAxis = ref(props.showAxisDefault)
const penVisible = ref(true)
const currentSpeed = ref(props.defaults.speed)
const errorMessage = ref('')
const errorSuggestion = ref('')

// 计算属性：命令按钮是否应该被禁用
const isCommandDisabled = computed(() => isRunning.value)
const showSuccessNotification = ref(false)
const canvasSnapshot = ref(null)
const canvasWidth = ref(900)   // 对应坐标范围 -450 到 450
const canvasHeight = ref(900)  // 对应坐标范围 -450 到 450
const drawCtxRef = ref(null)

// 命令按钮拖动相关状态
const isDragging = ref(false)
const dragStartX = ref(0)
const dragStartY = ref(0)
const buttonLeft = ref(null)
const buttonTop = ref(null)
const hasMoved = ref(false) // 用于区分拖动和点击
const initialButtonLeft = ref(null) // 拖动开始时的按钮位置
const initialButtonTop = ref(null)

// 编辑器内容缓存 - 使用 shallowRef 避免深度响应式追踪
const editorContent = shallowRef('')
const isContentDirty = ref(false) // 标记内容是否已更改

// 字体大小控制
const fontSize = ref(20) // 默认字体大小
const MIN_FONT_SIZE = 10 // 最小字体大小
const MAX_FONT_SIZE = 24 // 最大字体大小

// 笔头动画状态
const penState = ref({ x: 0, y: 0, angle: 0, color: '#0000ff', size: 1 })
const displayX = ref(0)
const displayY = ref(0)
let animationFrameId = null // 暂时注释掉未使用的变量

// 执行控制
let cancelToken = null
let currentExecutionPromise = null
let currentTimeoutPromise = null

// Trace收集器
const traceCollector = ref(null)
const currentTrace = ref([])

// 错误处理器
const errorHandler = ref(new GocErrorHandler())
const warnings = ref([])

// 性能优化器
const performance = ref(new GocPerformance())
// 编辑器就绪监控
let editorReadyTimer = null
// 组件清理用的定时器引用
let canvasInitTimer = null
let centerViewTimer = null
let resizeObserver = null
let handleResize = null
let contentChangeTimeout = null // 内容变化防抖定时器

// 命令面板状态
const showCommandPanel = ref(false) // 默认展开命令面板，让用户更容易发现
const lastClickTime = ref(0) // 防止快速点击

// 颜色映射数据
const colorMap = {
  0: { name: "黑色", color: "#000000" },
  1: { name: "红色", color: "#FF0000" },
  2: { name: "蓝色", color: "#0000FF" },
  3: { name: "绿色", color: "#00FF00" },
  4: { name: "青色", color: "#00FFFF" },
  5: { name: "黄色", color: "#FFFF00" },
  6: { name: "栗色", color: "#800000" },
  7: { name: "深蓝色", color: "#000080" },
  8: { name: "浅灰色", color: "#C0C0C0" },
  9: { name: "粉色", color: "#FFC0CB" },
  10: { name: "深绿色", color: "#008000" },
  11: { name: "紫色", color: "#800080" },
  12: { name: "蓝绿色", color: "#008080" },
  13: { name: "金色", color: "#FFD700" },
  14: { name: "橙色", color: "#FFA500" },
  15: { name: "白色", color: "#FFFFFF" }
}


// 输入输出相关状态
const cinValue = ref('')
const coutValue = ref('')
const isWaitingForInput = ref(false)
const showPenInput = ref(false)
const penInputValue = ref('')
const penInputStyle = ref({})
const inputResolve = ref(null) // 用于等待输入完成的Promise
const inputMode = ref('window') // 'pen' 或 'window'，默认为窗口输入模式
const inputData = ref('') // 存储从窗口输入的数据
const clearEditorReadyTimer = () => {
  if (editorReadyTimer) {
    clearTimeout(editorReadyTimer)
    editorReadyTimer = null
  }
}

// 初始化 Monaco 编辑器
const initMonaco = async () => {
  logger.log('🔧 开始初始化Monaco编辑器')
  // 若在一定时间内未创建成功，则降级为备用编辑器
  clearEditorReadyTimer()
  editorReadyTimer = setTimeout(() => {
    if (!editor.value) {
      logger.warn('⏱️ Monaco未在预期时间内就绪，启用备用编辑器')
      setupFallbackEditor()
    }
  }, 2500)
  
  // 使用打包的Monaco Editor
  if (window.monaco) {
    logger.log('✅ Monaco已存在，直接设置')
    setupMonacoSafely()
  } else {
    logger.log('📦 Monaco未加载，尝试动态导入...')
    try {
      // 动态导入Monaco Editor
      const monaco = await import('monaco-editor')
      window.monaco = monaco
      logger.log('✅ Monaco动态导入成功')
      setupMonacoSafely()
    } catch (error) {
      logger.error('❌ Monaco动态导入失败:', error)
      setupFallbackEditor()
    }
  }
}

// 等容器可用再创建编辑器，避免空容器导致挂起
const setupMonacoSafely = () => {
  const maxTries = 50
  let tries = 0
  const tryInit = () => {
    const el = editorContainer.value
    const ready = !!el && el.offsetWidth > 0 && el.offsetHeight > 0
    logger.log(`🔍 容器检查 ${tries}/${maxTries}:`, { 
      exists: !!el, 
      width: el?.offsetWidth, 
      height: el?.offsetHeight, 
      ready 
    })
    
    if (!ready) {
      if (tries++ < maxTries) {
        return requestAnimationFrame(tryInit)
      }
      // 最后一次仍不可见，使用备用编辑器避免卡住
      logger.log('⚠️ 容器多次检查后仍不可见，启用备用编辑器')
      return setupFallbackEditor()
    }

    try {
      logger.log('🎯 开始创建Monaco编辑器...')
      // 注册语言
      monaco.languages.register({ id: 'goc' })
      logger.log('✅ 语言注册完成')
      
      monaco.languages.setMonarchTokensProvider('goc', gocLanguage)
      logger.log('✅ 语法高亮设置完成')

      monaco.languages.setLanguageConfiguration('goc', {
        comments: { lineComment: '//' },
        // 自动缩进配置
        indentationRules: {
          increaseIndentPattern: /^\s*\{[^}]*$|^\s*if\s*\([^)]*\)\s*$|^\s*for\s*\([^)]*\)\s*$|^\s*while\s*\([^)]*\)\s*$|^\s*else\s*$|^\s*do\s*$|^\s*switch\s*\([^)]*\)\s*$|^\s*case\s+.*:\s*$/,
          decreaseIndentPattern: /^\s*\}/
        },
        // 自动闭合配置
        brackets: [
          ['{', '}'],
          ['[', ']'],
          ['(', ')']
        ],
        autoClosingPairs: [
          { open: '{', close: '}', notIn: ['string', 'comment'] },
          { open: '[', close: ']', notIn: ['string', 'comment'] },
          { open: '(', close: ')', notIn: ['string', 'comment'] },
          { open: '"', close: '"', notIn: ['string'] },
          { open: "'", close: "'", notIn: ['string', 'comment'] }
        ],
        surroundingPairs: [
          { open: '{', close: '}' },
          { open: '[', close: ']' },
          { open: '(', close: ')' },
          { open: '"', close: '"' },
          { open: "'", close: "'" }
        ]
      })
      logger.log('✅ 语言配置完成')

      monaco.editor.defineTheme('goc-dark', {
        base: 'vs-dark',
        inherit: true,
        rules: [
          { token: 'comment', foreground: '6b8e23', fontStyle: 'italic' }
        ],
        colors: {}
      })
      logger.log('✅ 主题定义完成')

      logger.log('🚀 正在创建编辑器实例...')
      editor.value = monaco.editor.create(editorContainer.value, {
        value: props.value,
        //value: '', // 强制设置为空字符串，避免初始代码
        language: 'goc',
        theme: props.theme === 'vs-dark' ? 'goc-dark' : props.theme,
        automaticLayout: false, // 禁用自动布局，避免 ResizeObserver 错误
        readOnly: props.readOnly,
        minimap: { enabled: false },
        // 设置默认缩进为4个空格
        tabSize: 4,
        insertSpaces: true,
        detectIndentation: false, // 禁用自动检测缩进，使用我们设置的默认值
        // 自动缩进配置
        autoIndent: 'full', // 启用完整自动缩进
        autoClosingBrackets: 'always', // 总是自动闭合括号
        autoClosingQuotes: 'always', // 总是自动闭合引号
        autoSurround: 'languageDefined', // 使用语言定义的自动包围
        // 增强的自动闭合配置
        autoClosingOvertype: 'always', // 在已有右括号时自动覆盖
        autoClosingDelete: 'always', // 删除左括号时自动删除右括号
        // 其他编辑器配置
        wordWrap: 'on',
        lineNumbers: 'on',
        folding: true,
        selectOnLineNumbers: true,
        roundedSelection: false,
        cursorStyle: 'line',
        scrollBeyondLastLine: false,
        renderWhitespace: 'selection',
        fontSize: fontSize.value,
        fontFamily: 'Monaco, Consolas, "Courier New", monospace'
      })
      
      if (!editor.value) {
        throw new Error('Monaco editor instance is null')
      }
      logger.log('✅ Monaco编辑器创建成功!')

      logger.log('📝 设置轻量级内容变化监听器...')
      // 只标记内容已更改，不立即获取内容
      editor.value.onDidChangeModelContent(() => {
        isContentDirty.value = true
        // 使用更长的防抖延迟，减少更新频率
        if (contentChangeTimeout) {
          clearTimeout(contentChangeTimeout)
        }
        
        contentChangeTimeout = setTimeout(() => {
          // 只在真正需要时才获取内容
          if (isContentDirty.value) {
            try {
              // 按需获取内容
              const value = getEditorContentSafely()
              if (value !== null) {
                editorContent.value = value
                emit('update:value', value)
                isContentDirty.value = false
              }
            } catch (error) {
              logger.error('❌ 内容变化监听器错误:', error)
            }
          }
        }, 300) // 增加到300ms防抖延迟
      })
      logger.log('✅ 内容变化监听器设置完成')

      // 完全跳过初始代码设置，避免卡死
      logger.log('ℹ️ 跳过初始代码设置，编辑器保持空白状态')
      
      // 手动调整编辑器布局
      setTimeout(() => {
        if (editor.value) {
          editor.value.layout()
        }
      }, 100)
      
      // 成功创建，清理监控
      clearEditorReadyTimer()
      logger.log('🎉 Monaco编辑器完全就绪')
    } catch (error) {
      logger.error('❌ Monaco编辑器设置失败:', error)
      setupFallbackEditor()
    }
  }
  tryInit()
}

const setupMonaco = () => {
  // 降噪：仅保留一条关键信息
  logger.log('🔧 设置Monaco编辑器')
  setupMonacoSafely()
}

// 备用编辑器（当Monaco加载失败或容器不可用时）
const setupFallbackEditor = () => {
  try {
    const container = editorContainer.value
    if (!container) return
    const textarea = document.createElement('textarea')
    textarea.style.width = '100%'
    textarea.style.height = '100%'
    textarea.style.fontFamily = 'Monaco, Consolas, "Courier New", monospace'
    textarea.style.fontSize = `${fontSize.value}px`
    textarea.style.border = '1px solid #ccc'
    textarea.style.padding = '10px'
    textarea.style.resize = 'none'
    textarea.style.tabSize = '4' // 设置tab大小为4个空格
    textarea.value = props.value || ''
    
    // 为备用编辑器添加缩进和自动闭合括号支持
    textarea.addEventListener('keydown', (e) => {
      if (e.key === 'Tab') {
        e.preventDefault()
        const start = textarea.selectionStart
        const end = textarea.selectionEnd
        const value = textarea.value
        const newValue = value.substring(0, start) + '    ' + value.substring(end) // 插入4个空格
        textarea.value = newValue
        textarea.setSelectionRange(start + 4, start + 4)
      } else if (e.key === 'Enter') {
        // 处理回车键自动缩进
        e.preventDefault()
        const start = textarea.selectionStart
        const end = textarea.selectionEnd
        const value = textarea.value
        
        // 获取当前行内容
        const lines = value.substring(0, start).split('\n')
        const currentLine = lines[lines.length - 1]
        
        // 计算当前行的缩进
        const currentIndent = currentLine.match(/^\s*/)[0]
        let newIndent = currentIndent
        
        // 检查是否需要增加缩进（如果当前行以{结尾）
        if (currentLine.trim().endsWith('{')) {
          newIndent += '    ' // 增加4个空格缩进
        }
        
        // 插入换行和缩进
        const newValue = value.substring(0, start) + '\n' + newIndent + value.substring(end)
        textarea.value = newValue
        textarea.setSelectionRange(start + 1 + newIndent.length, start + 1 + newIndent.length)
      } else if (e.key === '(' || e.key === '[' || e.key === '{') {
        // 自动闭合括号
        e.preventDefault()
        const start = textarea.selectionStart
        const end = textarea.selectionEnd
        const value = textarea.value
        
        let closingBracket = ''
        switch (e.key) {
          case '(':
            closingBracket = ')'
            break
          case '[':
            closingBracket = ']'
            break
          case '{':
            closingBracket = '}'
            break
        }
        
        // 插入左括号和右括号，光标放在中间
        const newValue = value.substring(0, start) + e.key + closingBracket + value.substring(end)
        textarea.value = newValue
        textarea.setSelectionRange(start + 1, start + 1)
      } else if (e.key === ')' || e.key === ']' || e.key === '}') {
        // 如果光标右边已经有对应的右括号，则跳过输入，直接移动光标
        const start = textarea.selectionStart
        const end = textarea.selectionEnd
        const value = textarea.value
        
        if (start === end && start < value.length && value[start] === e.key) {
          e.preventDefault()
          textarea.setSelectionRange(start + 1, start + 1)
        }
      } else if (e.key === 'Backspace') {
        // 处理删除左括号时自动删除右括号
        const start = textarea.selectionStart
        const end = textarea.selectionEnd
        const value = textarea.value
        
        if (start === end && start > 0) {
          const charBefore = value[start - 1]
          const charAfter = value[start]
          
          // 检查是否是配对的括号
          if ((charBefore === '(' && charAfter === ')') ||
              (charBefore === '[' && charAfter === ']') ||
              (charBefore === '{' && charAfter === '}')) {
            e.preventDefault()
            // 删除左括号和右括号
            const newValue = value.substring(0, start - 1) + value.substring(start + 1)
            textarea.value = newValue
            textarea.setSelectionRange(start - 1, start - 1)
          }
        }
      }
    })

    container.innerHTML = ''
    container.appendChild(textarea)

        editor.value = {
          getValue: () => textarea.value,
          setValue: (value) => { 
            textarea.value = value || ''
            editorContent.value = value || ''
            isContentDirty.value = false
          },
          onDidChangeModelContent: (callback) => {
            textarea.addEventListener('input', () => {
              // 只标记内容已更改，不立即触发回调
              isContentDirty.value = true
              // 使用更长的防抖延迟
              if (contentChangeTimeout) {
                clearTimeout(contentChangeTimeout)
              }
              contentChangeTimeout = setTimeout(() => {
                if (isContentDirty.value) {
                  callback()
                  isContentDirty.value = false
                }
              }, 300)
            })
          },
          updateOptions: () => {},
          dispose: () => {}
        }

    textarea.addEventListener('input', () => {
      // 只标记内容已更改，不立即触发事件
      isContentDirty.value = true
      // 使用更长的防抖延迟
      if (contentChangeTimeout) {
        clearTimeout(contentChangeTimeout)
      }
      contentChangeTimeout = setTimeout(() => {
        if (isContentDirty.value) {
          const value = textarea.value
          editorContent.value = value
          emit('update:value', value)
          isContentDirty.value = false
        }
      }, 300)
    })
    // 备用编辑器就绪，清理监控
    clearEditorReadyTimer()
  } catch (e) {
    logger.error('❌ 备用编辑器设置失败:', e)
  }
}

// 初始化画布
let canvasInitRetryCount = 0
const MAX_CANVAS_INIT_RETRIES = 50

const initCanvas = () => {
  // 检查重试次数
  if (canvasInitRetryCount >= MAX_CANVAS_INIT_RETRIES) {
    logger.error('Canvas初始化失败：超过最大重试次数')
    return
  }
  
  // 检查Canvas元素是否存在
  if (!axisCanvas.value || !drawCanvas.value || !penCanvas.value) {
    canvasInitRetryCount++
    logger.warn(`Canvas元素尚未准备好，延迟初始化... (${canvasInitRetryCount}/${MAX_CANVAS_INIT_RETRIES})`)
    canvasInitTimer = setTimeout(initCanvas, 100)
    return
  }
  
  // 检查Canvas元素是否已经挂载到DOM
  if (!axisCanvas.value.parentNode || !drawCanvas.value.parentNode || !penCanvas.value.parentNode) {
    canvasInitRetryCount++
    logger.warn(`Canvas元素尚未挂载到DOM，延迟初始化... (${canvasInitRetryCount}/${MAX_CANVAS_INIT_RETRIES})`)
    canvasInitTimer = setTimeout(initCanvas, 100)
    return
  }
  
  let penCtx
  try {
    drawCtxRef.value = drawCanvas.value.getContext('2d') 
    penCtx = penCanvas.value.getContext('2d')
    
    if (!drawCtxRef.value || !penCtx) {
      throw new Error('无法获取Canvas上下文')
    }
  } catch (error) {
    canvasInitRetryCount++
    logger.error(`Canvas初始化失败: ${error.message} (${canvasInitRetryCount}/${MAX_CANVAS_INIT_RETRIES})`)
    if (canvasInitRetryCount < MAX_CANVAS_INIT_RETRIES) {
      canvasInitTimer = setTimeout(initCanvas, 100)
    }
    return
  }

  // 设置笔头动画回调
  window.__gocUpdatePen = (x, y, angle, color, size) => {
    penState.value = { x, y, angle, color: color || '#0000ff', size: size || 1 }
  }

  window.__gocSetPenVisible = (visible) => {
    penVisible.value = !!visible
    if (!penVisible.value) {
      penCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
    }
  }

  // 优化的笔头动画循环
  const renderPen = () => { // 移除未使用的deltaTime参数
    if (!penVisible.value) return

    penCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
    
    // 缓动到目标位置 - 智能同步算法
    const deltaX = penState.value.x - displayX.value
    const deltaY = penState.value.y - displayY.value
    const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
    
    // 如果距离很小，直接设置为目标位置，避免无限接近
    if (distance < 0.5) {
      displayX.value = penState.value.x
      displayY.value = penState.value.y
    } else if (distance > 10) {
      // 距离较大时，使用更快的缓动系数，快速追上
      displayX.value += deltaX * 0.8
      displayY.value += deltaY * 0.8
    } else {
      // 中等距离时，使用平衡的缓动系数
      displayX.value += deltaX * 0.6
      displayY.value += deltaY * 0.6
    }
    
    penCtx.save()
    penCtx.translate(toCanvasX(displayX.value), toCanvasY(displayY.value))
    // 重新设计画笔视觉显示角度计算
    // 画笔默认方向向右，要让角度0显示向上，需要旋转-90度
    let visualAngle = penState.value.angle - 90;
    penCtx.rotate(visualAngle * Math.PI / 180)
    
    // 绘制钢笔
    const baseLen = 30
    const baseWidth = 9
    const s = Math.max(0.7, Math.min(2.5, 0.6 + (penState.value.size || 1) * 0.18))
    const length = baseLen * s
    const width = baseWidth * s
    const nibLen = length * 0.42
    const bodyLen = length - nibLen
    const color = penState.value.color || '#0000ff'
    const darkStroke = '#222'

    penCtx.lineWidth = Math.max(1, 1.2 * s)
    penCtx.strokeStyle = darkStroke

    // 笔身
    const rx = width / 2
    const bodyX = -length / 2
    const bodyY = -width / 2
    const r = rx
    penCtx.beginPath()
    penCtx.moveTo(bodyX + r, bodyY)
    penCtx.lineTo(bodyX + bodyLen - r, bodyY)
    penCtx.quadraticCurveTo(bodyX + bodyLen, bodyY, bodyX + bodyLen, bodyY + r)
    penCtx.lineTo(bodyX + bodyLen, bodyY + width - r)
    penCtx.quadraticCurveTo(bodyX + bodyLen, bodyY + width, bodyX + bodyLen - r, bodyY + width)
    penCtx.lineTo(bodyX + r, bodyY + width)
    penCtx.quadraticCurveTo(bodyX, bodyY + width, bodyX, bodyY + width - r)
    penCtx.lineTo(bodyX, bodyY + r)
    penCtx.quadraticCurveTo(bodyX, bodyY, bodyX + r, bodyY)
    penCtx.closePath()
    penCtx.fillStyle = color
    penCtx.fill()
    penCtx.stroke()

    // 金属笔圈
    const ringW = 2.8 * s
    const ringH = width * 1.2
    const ringX = -length / 2 + bodyLen - 2 * s
    const ringY = -ringH / 2
    const ringGrad = penCtx.createLinearGradient(ringX, 0, ringX + ringW, 0)
    ringGrad.addColorStop(0.0, '#f2f2f2')
    ringGrad.addColorStop(0.2, '#d8d8d8')
    ringGrad.addColorStop(0.5, '#9a9a9a')
    ringGrad.addColorStop(0.8, '#d8d8d8')
    ringGrad.addColorStop(1.0, '#f2f2f2')
    penCtx.beginPath()
    penCtx.rect(ringX, ringY, ringW, ringH)
    penCtx.fillStyle = ringGrad
    penCtx.fill()
    penCtx.strokeStyle = '#666'
    penCtx.stroke()

    // 高光细线
    penCtx.beginPath()
    penCtx.moveTo(ringX + 0.5 * s, ringY + 1)
    penCtx.lineTo(ringX + 0.5 * s, ringY + ringH - 1)
    penCtx.strokeStyle = 'rgba(255,255,255,0.7)'
    penCtx.lineWidth = Math.max(0.6, 0.6 * s)
    penCtx.stroke()

    // 暗部细线
    penCtx.beginPath()
    penCtx.moveTo(ringX + ringW * 0.6, ringY + 1)
    penCtx.lineTo(ringX + ringW * 0.6, ringY + ringH - 1)
    penCtx.strokeStyle = 'rgba(0,0,0,0.25)'
    penCtx.lineWidth = Math.max(0.6, 0.6 * s)
    penCtx.stroke()

    // 笔尖
    const baseX = -length / 2 + bodyLen
    penCtx.beginPath()
    penCtx.moveTo(baseX, -width / 2)
    penCtx.lineTo(length / 2, 0)
    penCtx.lineTo(baseX, width / 2)
    penCtx.closePath()
    penCtx.fillStyle = '#333'
    penCtx.fill()
    penCtx.stroke()

    // 透气孔
    const holeR = Math.max(1.1, 1.3 * s)
    const holeX = baseX + nibLen * 0.45
    const holeY = 0
    const holeGrad = penCtx.createRadialGradient(holeX - 0.3 * s, holeY - 0.3 * s, 0, holeX, holeY, holeR)
    holeGrad.addColorStop(0.0, '#ffffff')
    holeGrad.addColorStop(0.35, '#dddddd')
    holeGrad.addColorStop(0.7, '#9a9a9a')
    holeGrad.addColorStop(1.0, '#4a4a4a')
    penCtx.beginPath()
    penCtx.arc(holeX, holeY, holeR, 0, Math.PI * 2)
    penCtx.fillStyle = holeGrad
    penCtx.fill()
    penCtx.strokeStyle = '#222'
    penCtx.lineWidth = Math.max(0.8, 0.9 * s)
    penCtx.stroke()

    // 高光点
    penCtx.beginPath()
    penCtx.arc(holeX - 0.35 * s, holeY - 0.35 * s, Math.max(0.5, 0.5 * s), 0, Math.PI * 2)
    penCtx.fillStyle = 'rgba(255,255,255,0.9)'
    penCtx.fill()

    // 裂缝线
    const slitStartX = holeX
    const slitEndX = length / 2 - 1.5 * s
    penCtx.beginPath()
    penCtx.moveTo(slitStartX, 0)
    penCtx.lineTo(slitEndX, 0)
    penCtx.lineWidth = Math.max(1.5, 1.5 * s)
    penCtx.strokeStyle = 'rgba(0,0,0,0.5)'
    penCtx.stroke()

    penCtx.beginPath()
    penCtx.moveTo(slitStartX, 0)
    penCtx.lineTo(slitEndX, 0)
    penCtx.lineWidth = Math.max(0.7, 0.8 * s)
    penCtx.strokeStyle = 'rgba(255,255,255,0.85)'
    penCtx.stroke()

    penCtx.restore()
  }

  // 使用性能优化的动画循环
  performance.value.optimizedAnimationLoop(renderPen, 60)
}

// 坐标转换函数
const toCanvasX = (logicalX) => {
  // 将逻辑坐标(-450到450)转换为画布坐标(0到900)
  // 逻辑坐标0对应画布坐标400
  return canvasWidth.value / 2 + logicalX
}

const toCanvasY = (logicalY) => {
  // 将逻辑坐标(-450到450)转换为画布坐标(0到900)
  // 逻辑坐标0对应画布坐标400，Y轴向上为正
  return canvasHeight.value / 2 - logicalY
}

// 绘制坐标轴
const drawAxis = () => {
  if (!axisCanvas.value) return
  
  const ctx = axisCanvas.value.getContext('2d')
  ctx.save()
  ctx.strokeStyle = 'red'
  ctx.lineWidth = 1
  ctx.setLineDash([5, 5])

  const centerX = canvasWidth.value / 2  // 450
  const centerY = canvasHeight.value / 2 // 450
  const gridInterval = 100  // 网格间隔100像素，对应逻辑坐标100

  // 水平网格线 (Y轴方向)
  ctx.beginPath()
  for (let y = -400; y <= 400; y += 100) {
    const yPos = toCanvasY(y)
    ctx.moveTo(0, yPos)
    ctx.lineTo(canvasWidth.value, yPos)
  }
  ctx.stroke()

  // 垂直网格线 (X轴方向)
  ctx.beginPath()
  for (let x = -400; x <= 400; x += 100) {
    const xPos = toCanvasX(x)
    ctx.moveTo(xPos, 0)
    ctx.lineTo(xPos, canvasHeight.value)
  }
  ctx.stroke()

  // 刻度标签
  ctx.fillStyle = 'black'
  ctx.font = '14px Arial'
  
  // X轴刻度标签 - 显示整百数值
  for (let x = -400; x <= 400; x += 100) {
    const xPos = toCanvasX(x)
    ctx.textAlign = 'center'
    ctx.fillText(x.toString(), xPos, 20)
  }

  // Y轴刻度标签 - 显示整百数值
  for (let y = -400; y <= 400; y += 100) {
    const yPos = toCanvasY(y)
    ctx.textAlign = 'right'
    ctx.fillText(y.toString(), 20, yPos + 4)
  }

  // 原点标记
  ctx.beginPath()
  ctx.arc(centerX, centerY, 3, 0, Math.PI * 2)
  ctx.fillStyle = 'red'
  ctx.fill()

  // 主轴线已由网格线绘制，无需单独绘制

  ctx.restore()
}

// 运行代码
const run = async (code) => {
  const ctx = drawCtxRef.value
  ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)

  logger.log('🚀 运行按钮被点击')
  logger.log('📝 编辑器状态:', editor.value)
  logger.log('⚡ 是否正在运行:', isRunning.value)
  
  if (isRunning.value) return
  
  // 重置画笔状态到初始位置
  resetPenState()
  
  // 确保画笔动画循环正在运行
  if (performance.value && !performance.value.isAnimating) {
    try {
      // 重新启动动画循环
      const penCtx = penCanvas.value?.getContext('2d')
      if (penCtx) {
        const renderPen = () => {
          if (!penVisible.value) return
          penCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
          
          // 缓动到目标位置 - 智能同步算法
          const deltaX = penState.value.x - displayX.value
          const deltaY = penState.value.y - displayY.value
          const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
          
          // 如果距离很小，直接设置为目标位置，避免无限接近
          if (distance < 0.5) {
            displayX.value = penState.value.x
            displayY.value = penState.value.y
          } else if (distance > 10) {
            // 距离较大时，使用更快的缓动系数，快速追上
            displayX.value += deltaX * 0.8
            displayY.value += deltaY * 0.8
          } else {
            // 中等距离时，使用平衡的缓动系数
            displayX.value += deltaX * 0.6
            displayY.value += deltaY * 0.6
          }
          
          penCtx.save()
          penCtx.translate(toCanvasX(displayX.value), toCanvasY(displayY.value))
          penCtx.rotate((-penState.value.angle) * Math.PI / 180)
          
          // 绘制钢笔（简化版本）
          const baseLen = 30
          const baseWidth = 9
          const s = Math.max(0.7, Math.min(2.5, 0.6 + (penState.value.size || 1) * 0.18))
          const length = baseLen * s
          const width = baseWidth * s
          const color = penState.value.color || '#0000ff'
          
          penCtx.fillStyle = color
          penCtx.fillRect(-length/2, -width/2, length, width)
          penCtx.restore()
        }
        
        performance.value.optimizedAnimationLoop(renderPen, 60)
        logger.log('✅ 画笔动画循环已重新启动')
      }
    } catch (error) {
      logger.warn('⚠️ 重新启动画笔动画循环时出错:', error)
    }
  }

  let codeToRun = ''
  // 检查传入的code是否是有效字符串，而不是事件对象
  if (code && typeof code === 'string' && !code.includes('PointerEvent')) {
    codeToRun = String(code)
    logger.log('✅ 使用传入的代码参数')
  } else {
    logger.log('🔍 按需获取编辑器内容...')
    // 使用按需获取，避免实时监听
    codeToRun = getCode()
    logger.log('✅ 获取内容完成，长度:', codeToRun.length)
  }
  
  logger.log('📄 要运行的代码:', codeToRun, '类型:', typeof codeToRun)
  
  if (!codeToRun || !codeToRun.trim()) {
    logger.log('❌ 代码为空，无法运行')
    return
  }

  // 初始化取消令牌
  cancelToken = { cancel: false }
  currentExecutionPromise = null
  currentTimeoutPromise = null
  
  isRunning.value = true
  errorMessage.value = ''
  errorSuggestion.value = ''
  showSuccessNotification.value = false
  warnings.value = []
  // 清空输出框内容，确保每次运行都是新的输出
  coutValue.value = ''
  emit('run-start')

  try {
    // 代码验证
    warnings.value = errorHandler.value.validateCode(codeToRun)
    
    // 检查是否有错误级别的警告
    const errors = warnings.value.filter(w => w.type === 'error')
    if (errors.length > 0) {
      // 显示第一个错误
      const firstError = errors[0]
      errorMessage.value = firstError.message
      errorSuggestion.value = firstError.suggestion || ''
      isRunning.value = false
      return
    }
    
    if (warnings.value.length > 0) {
      logger.warn('代码警告:', warnings.value)
    }

    // 初始化Trace收集器
    if (props.traceEnabled) {
      traceCollector.value = new TraceCollector()
    }

    // 清空绘制画布
    const ctx = drawCanvas.value.getContext('2d')
    ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)

    // 清空坐标轴画布并重新绘制
    if (axisCanvas.value) {
      const axisCtx = axisCanvas.value.getContext('2d')
      axisCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
      
      if (showAxis.value) {
        drawAxis()
      }
    }

    // 执行代码（带超时控制和取消检查）
    currentExecutionPromise = executeCode(codeToRun, ctx, cancelToken)
    currentTimeoutPromise = new Promise((_, reject) => {
      setTimeout(() => {
        if (!cancelToken.cancel) {
          reject(new Error('TIMEOUT'))
        }
      }, 120000) // 2分钟超时
    })

    await Promise.race([currentExecutionPromise, currentTimeoutPromise])

    // 保存Trace数据
    if (props.traceEnabled && traceCollector.value) {
      currentTrace.value = traceCollector.value.getTrace()
      emit('trace', currentTrace.value)
    }

    // 执行完成后保存绘制画布状态（用于坐标轴切换功能）
    if (showAxis.value) {
      try {
        canvasSnapshot.value = ctx.getImageData(0, 0, canvasWidth.value, canvasHeight.value)
      } catch (e) {
        canvasSnapshot.value = null
      }
    }

    // 显示成功提示
    showSuccessNotification.value = true
    setTimeout(() => {
      showSuccessNotification.value = false
    }, 3000) // 3秒后自动隐藏

    emit('run-end')
  } catch (error) {
    // 如果是用户取消，不显示错误信息
    if (error.message === 'CANCELLED') {
      logger.log('✅ 代码执行被用户成功取消')
      return
    }
    
    let errorInfo
    if (error.message === 'TIMEOUT') {
      errorInfo = errorHandler.value.handleTimeoutError(120000, '代码执行')
    } else if (error.name === 'SyntaxError') {
      errorInfo = errorHandler.value.handleSyntaxError(error, codeToRun)
    } else if (error.name === 'ReferenceError' || error.name === 'TypeError') {
      errorInfo = errorHandler.value.handleRuntimeError(error)
    } else {
      errorInfo = errorHandler.value.handleRuntimeError(error)
    }

    errorMessage.value = errorInfo.message
    errorSuggestion.value = errorInfo.suggestion || ''
    emit('error', errorInfo)
  } finally {
    isRunning.value = false
    // 清理执行相关的Promise引用
    currentExecutionPromise = null
    currentTimeoutPromise = null
  }
}

// 执行代码的辅助函数
const executeCode = async (code, ctx, cancelToken) => {
  try {
    logger.log('🔍 开始解析代码...')
    
    // 检查是否已被取消
    if (cancelToken && cancelToken.cancel) {
      logger.log('🛑 代码执行被取消')
      throw new Error('CANCELLED')
    }
    
    const tokens = tokenize(code)
    logger.log('✅ Tokenizer完成，tokens:', tokens)
    
    // 检查是否已被取消
    if (cancelToken && cancelToken.cancel) {
      logger.log('🛑 代码执行被取消')
      throw new Error('CANCELLED')
    }
    
    const ast = parse(tokens)
    logger.log('✅ Parser完成，AST:', ast)
    
    // 检查是否已被取消
    if (cancelToken && cancelToken.cancel) {
      logger.log('🛑 代码执行被取消')
      throw new Error('CANCELLED')
    }
    
    await execute(ast, ctx, traceCollector.value, {
      waitForInput,
      outputToCout,
      setInputMode
    }, cancelToken)
    logger.log('✅ 代码执行完成')
    
    // 执行完成后同步速度下拉框
    syncSpeedFromGlobal()
  } catch (error) {
    if (error.message === 'CANCELLED') {
      logger.log('🛑 代码执行被用户取消')
    } else {
      logger.error('❌ 代码执行失败:', error)
    }
    throw error
  }
}

// 重置画笔状态
const resetPenState = () => {
  logger.log('🔄 重置画笔状态')
  
  // 重置画笔位置和角度到初始状态
  penState.value = { x: 0, y: 0, angle: 0, color: '#0000ff', size: 1 }
  displayX.value = 0
  displayY.value = 0
  
  // 重置画笔可见性状态
  penVisible.value = true
  
  // 更新画笔显示
  if (window.__gocUpdatePen) {
    window.__gocUpdatePen(0, 0, 0, '#0000ff', 1)
  }
  
  // 重置画笔可见性
  if (window.__gocSetPenVisible) {
    window.__gocSetPenVisible(true)
  }
  
  logger.log('✅ 画笔状态已重置')
}

// 停止执行
const stop = () => {
  logger.log('🛑 停止按钮被点击')
  
  // 设置取消标志
  if (cancelToken) {
    cancelToken.cancel = true
    logger.log('✅ 取消标志已设置')
  }
  
  // 立即停止运行状态
  isRunning.value = false
  
  // 清理所有可能的异步操作
  if (currentExecutionPromise) {
    logger.log('🛑 取消当前执行Promise')
    currentExecutionPromise = null
  }
  
  // 清理超时Promise
  if (currentTimeoutPromise) {
    logger.log('🛑 取消超时Promise')
    currentTimeoutPromise = null
  }
  
  // 注意：不停止性能优化器的动画，让画笔动画继续运行
  // 这样画笔可以继续响应状态更新
  
  // 注意：停止按钮不应该重置画笔状态，画笔应该停留在当前位置
  // 只有清空按钮才应该重置画笔状态
  
  logger.log('✅ 停止操作完成')
}

// 清空画布
const clear = () => {
  const ctx = drawCtxRef.value
  ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
  
  // 清空坐标轴画布
  if (axisCanvas.value) {
    const axisCtx = axisCanvas.value.getContext('2d')
    axisCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
    
    // 如果显示坐标轴，重新绘制
    if (showAxis.value) {
      drawAxis()
    }
  }
  
  // 重置画笔状态到原点
  resetPenState()
  
  canvasSnapshot.value = null
}

// 清除错误提示
const clearError = () => {
  errorMessage.value = ''
  errorSuggestion.value = ''
}

// 切换坐标轴显示
const toggleAxis = () => {
  showAxis.value = !showAxis.value
  
  if (axisCanvas.value) {
    const axisCtx = axisCanvas.value.getContext('2d')
    axisCtx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
    
    if (showAxis.value) {
      drawAxis()
    }
  }
}

// 切换笔显示
const togglePen = () => {
  penVisible.value = !penVisible.value
  if (window.__gocSetPenVisible) {
    window.__gocSetPenVisible(penVisible.value)
  }
}

// 居中显示画布
const centerView = () => {
  const scrollContainer = document.querySelector('.canvas-scroll-container')
  if (scrollContainer) {
    // 滚动到画布中心位置
    const centerX = (900 - scrollContainer.clientWidth) / 2
    const centerY = (900 - scrollContainer.clientHeight) / 2
    scrollContainer.scrollTo({
      left: Math.max(0, centerX),
      top: Math.max(0, centerY),
      behavior: 'smooth'
    })
  }
}

// 设置速度
const setSpeed = () => {
  const speed = parseInt(currentSpeed.value)
  logger.log(`设置速度等级为: ${speed}`)
  
  // 设置全局速度变量，供interpreter使用
  window.__gocSpeedLevel = speed
  
  // 如果解释器正在运行，立即更新其内部速度变量
  if (window.__gocUpdateSpeed) {
    window.__gocUpdateSpeed(speed)
  }
  
  // 更新笔状态
  if (window.__gocUpdatePen) {
    window.__gocUpdatePen(penState.value.x, penState.value.y, penState.value.angle, penState.value.color, penState.value.size)
  }
}

// 监听全局速度变化，同步更新下拉框
const syncSpeedFromGlobal = () => {
  if (window.__gocSpeedLevel && window.__gocSpeedLevel !== parseInt(currentSpeed.value)) {
    currentSpeed.value = window.__gocSpeedLevel.toString()
    logger.log(`同步速度下拉框: ${currentSpeed.value}`)
  }
}

// 字体大小控制方法
const increaseFontSize = () => {
  if (fontSize.value < MAX_FONT_SIZE) {
    fontSize.value += 1
    updateEditorFontSize()
    // 保存到本地存储
    localStorage.setItem('goc-editor-font-size', fontSize.value.toString())
  }
}

const decreaseFontSize = () => {
  if (fontSize.value > MIN_FONT_SIZE) {
    fontSize.value -= 1
    updateEditorFontSize()
    // 保存到本地存储
    localStorage.setItem('goc-editor-font-size', fontSize.value.toString())
  }
}

const updateEditorFontSize = () => {
  // 更新Monaco编辑器字体大小
  if (editor.value && editor.value.updateOptions) {
    editor.value.updateOptions({
      fontSize: fontSize.value
    })
  }
  
  // 更新备用编辑器的字体大小
  const container = editorContainer.value
  if (container) {
    const textarea = container.querySelector('textarea')
    if (textarea) {
      textarea.style.fontSize = `${fontSize.value}px`
    }
  }
}

// 安全获取编辑器内容的函数
const getEditorContentSafely = () => {
  if (!editor.value) return null
  
  try {
    // 优先使用Monaco API
    if (editor.value.getValue && typeof editor.value.getValue === 'function') {
      return editor.value.getValue()
    }
    
    // 如果Monaco API失败，使用简单的DOM方法作为备用
    const container = editorContainer.value
    if (container) {
      const textarea = container.querySelector('textarea')
      if (textarea) {
        return textarea.value || ''
      }
    }
    
    return null
  } catch (error) {
    logger.warn('⚠️ 获取编辑器内容失败:', error)
    return null
  }
}

// 获取代码 - 按需获取
const getCode = () => {
  // 如果内容已更改，先获取最新内容
  if (isContentDirty.value) {
    const value = getEditorContentSafely()
    if (value !== null) {
      editorContent.value = value
      isContentDirty.value = false
      return value
    }
  }
  
  // 返回缓存的内容
  return editorContent.value || ''
}

// 设置代码
const setCode = (value) => {
  if (editor.value) {
    const newValue = value || ''
    editor.value.setValue(newValue)
    // 更新缓存，避免不必要的重新获取
    editorContent.value = newValue
    isContentDirty.value = false
  }
}

// 设置主题
const setTheme = (theme) => {
  if (editor.value) {
    const themeName = theme === 'vs-dark' ? 'goc-dark' : theme
    monaco.editor.setTheme(themeName)
  }
}

// 获取Trace数据
const getTrace = () => {
  return currentTrace.value
}

// 获取画布图片数据
const getCanvasImage = () => {
  return new Promise((resolve, reject) => {
    try {
      if (!drawCanvas.value) {
        reject(new Error('画布未初始化'))
        return
      }
      
      // 获取画布的ImageData
      const canvas = drawCanvas.value
      const imageData = canvas.toDataURL('image/png')
      resolve(imageData)
    } catch (error) {
      logger.error('获取画布图片失败:', error)
      reject(error)
    }
  })
}

// 导出 trace
const exportTrace = () => {
  if (traceCollector.value) {
    return traceCollector.value.exportJSON()
  }
  return JSON.stringify({ trace: currentTrace.value, stats: {}, metadata: {} })
}

// 回放 trace
const replay = (trace) => {
  if (Array.isArray(trace)) {
    currentTrace.value = trace
    logger.log('Trace loaded for replay:', trace.length, 'actions')
  }
}

// 获取光标位置
const getCursorPosition = () => {
  if (editor.value) {
    const position = editor.value.getPosition()
    return position
  }
  return { lineNumber: 1, column: 1 }
}

// 设置光标位置
const setCursorPosition = (position) => {
  if (editor.value) {
    editor.value.setPosition(position)
    editor.value.focus()
  }
}


// 在当前光标位置插入文本 - 使用DOM方式避免Monaco API卡死
const insertTextAtCursor = (text) => {
  try {
    logger.log('🔍 开始插入文本:', text)
    const container = editorContainer.value
    if (!container) {
      logger.warn('编辑器容器不存在')
      return
    }

    logger.log('📦 编辑器容器:', container)
    logger.log('📦 容器HTML:', container.innerHTML.substring(0, 200) + '...')

    // 查找textarea或contentEditable元素
    const textarea = container.querySelector('textarea')
    const contentEditable = container.querySelector('[contenteditable="true"]')
    
    logger.log('🔍 找到的元素:', { textarea: !!textarea, contentEditable: !!contentEditable })
    
    if (textarea) {
      logger.log('📝 使用textarea插入')
      const start = textarea.selectionStart
      const end = textarea.selectionEnd
      const currentValue = textarea.value
      
      logger.log('📍 光标位置:', { start, end, currentValue: currentValue.substring(0, 50) + '...' })
      
      // 插入文本
      const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)
      textarea.value = newValue
      
      // 设置光标位置到插入文本的末尾
      const newCursorPos = start + text.length
      textarea.setSelectionRange(newCursorPos, newCursorPos)
      textarea.focus()
      
      logger.log('✅ 文本插入完成，新光标位置:', newCursorPos)
      
      // 只触发基本事件，避免复杂的Monaco API调用
      textarea.dispatchEvent(new Event('input', { bubbles: true }))
      textarea.dispatchEvent(new Event('change', { bubbles: true }))
      
      // 尝试使用键盘事件来触发Monaco更新
      const keyEvent = new KeyboardEvent('keydown', {
        key: 'a',
        code: 'KeyA',
        bubbles: true,
        cancelable: true
      })
      textarea.dispatchEvent(keyEvent)
      
      // 延迟触发keyup事件
      setTimeout(() => {
        const keyUpEvent = new KeyboardEvent('keyup', {
          key: 'a',
          code: 'KeyA',
          bubbles: true,
          cancelable: true
        })
        textarea.dispatchEvent(keyUpEvent)
      }, 10)
      
    } else if (contentEditable) {
      logger.log('📝 使用contentEditable插入')
      const selection = window.getSelection()
      if (selection.rangeCount > 0) {
        const range = selection.getRangeAt(0)
        range.deleteContents()
        range.insertNode(document.createTextNode(text))
        range.collapse(false)
        selection.removeAllRanges()
        selection.addRange(range)
        logger.log('✅ contentEditable插入完成')
      } else {
        logger.warn('没有选中的范围')
      }
      
    } else {
      logger.warn('未找到可编辑的DOM元素')
      // 尝试查找Monaco编辑器的DOM元素
      const monacoEditor = container.querySelector('.monaco-editor')
      const viewLines = container.querySelector('.view-lines')
      const viewLine = container.querySelector('.view-line')
      
      logger.log('🔍 Monaco相关元素:', { 
        monacoEditor: !!monacoEditor, 
        viewLines: !!viewLines, 
        viewLine: !!viewLine 
      })
      
      if (monacoEditor) {
        logger.log('🎯 找到Monaco编辑器DOM元素')
        // 尝试在Monaco编辑器中插入文本
        const textarea = monacoEditor.querySelector('textarea')
        if (textarea) {
          logger.log('📝 在Monaco编辑器的textarea中插入')
          const start = textarea.selectionStart
          const end = textarea.selectionEnd
          const currentValue = textarea.value
          
          const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)
          textarea.value = newValue
          
          const newCursorPos = start + text.length
          textarea.setSelectionRange(newCursorPos, newCursorPos)
          textarea.focus()
          
          textarea.dispatchEvent(new Event('input', { bubbles: true }))
          logger.log('✅ Monaco编辑器textarea插入完成')
        } else {
          logger.log('❌ Monaco编辑器中未找到textarea')
          // 尝试其他方式
          const input = monacoEditor.querySelector('input')
          if (input) {
            logger.log('📝 在Monaco编辑器的input中插入')
            const start = input.selectionStart
            const end = input.selectionEnd
            const currentValue = input.value
            
            const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)
            input.value = newValue
            
            const newCursorPos = start + text.length
            input.setSelectionRange(newCursorPos, newCursorPos)
            input.focus()
            
            input.dispatchEvent(new Event('input', { bubbles: true }))
            logger.log('✅ Monaco编辑器input插入完成')
          }
        }
      } else {
        logger.log('❌ 未找到Monaco编辑器DOM元素')
        // 尝试直接在整个容器中查找textarea
        const allTextareas = container.querySelectorAll('textarea')
        logger.log('🔍 容器中所有textarea:', allTextareas.length)
        if (allTextareas.length > 0) {
          const textarea = allTextareas[0]
          logger.log('📝 使用第一个找到的textarea')
          const start = textarea.selectionStart
          const end = textarea.selectionEnd
          const currentValue = textarea.value
          
          const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)
          textarea.value = newValue
          
          const newCursorPos = start + text.length
          textarea.setSelectionRange(newCursorPos, newCursorPos)
          textarea.focus()
          
          textarea.dispatchEvent(new Event('input', { bubbles: true }))
          logger.log('✅ 使用第一个textarea插入完成')
        }
      }
    }
  } catch (error) {
    logger.error('DOM方式插入文本失败:', error)
  }
}

// 模拟键盘输入来插入文本
const simulateKeyboardInput = (text) => {
  try {
    const container = editorContainer.value
    if (!container) return false
    
    const textarea = container.querySelector('textarea')
    if (!textarea) return false
    
    // 确保textarea获得焦点
    textarea.focus()
    
    // 模拟逐个字符输入
    for (let i = 0; i < text.length; i++) {
      const char = text[i]
      
      // 模拟keydown事件
      const keydownEvent = new KeyboardEvent('keydown', {
        key: char,
        code: `Key${char.toUpperCase()}`,
        bubbles: true,
        cancelable: true
      })
      textarea.dispatchEvent(keydownEvent)
      
      // 模拟keypress事件
      const keypressEvent = new KeyboardEvent('keypress', {
        key: char,
        code: `Key${char.toUpperCase()}`,
        bubbles: true,
        cancelable: true
      })
      textarea.dispatchEvent(keypressEvent)
      
      // 实际插入字符
      const start = textarea.selectionStart
      const end = textarea.selectionEnd
      const currentValue = textarea.value
      const newValue = currentValue.substring(0, start) + char + currentValue.substring(end)
      textarea.value = newValue
      
      // 更新光标位置
      const newCursorPos = start + 1
      textarea.setSelectionRange(newCursorPos, newCursorPos)
      
      // 模拟keyup事件
      const keyupEvent = new KeyboardEvent('keyup', {
        key: char,
        code: `Key${char.toUpperCase()}`,
        bubbles: true,
        cancelable: true
      })
      textarea.dispatchEvent(keyupEvent)
      
      // 触发input事件
      const inputEvent = new Event('input', { bubbles: true })
      textarea.dispatchEvent(inputEvent)
    }
    
    logger.log('✅ 模拟键盘输入完成')
    return true
  } catch (error) {
    logger.error('模拟键盘输入失败:', error)
    return false
  }
}

// 插入命令 - 使用模拟键盘输入，避免Monaco API卡死
const insertCommand = (command) => {
  try {
    // 如果正在运行，阻止插入命令
    if (isRunning.value) {
      logger.log('⚠️ 代码正在运行，无法插入命令')
      return
    }
    
    // 防止快速点击（防抖）
    const now = Date.now()
    if (now - lastClickTime.value < 100) {
      return
    }
    lastClickTime.value = now
    
    logger.log('🚀 开始插入命令:', command)
    
    // 尝试模拟键盘输入
    if (simulateKeyboardInput(command)) {
      return
    }
    
    // 如果模拟键盘输入失败，使用简单的DOM方式
    logger.log('🔄 模拟键盘输入失败，使用简单DOM方式')
    insertTextAtCursor(command)
    
  } catch (error) {
    logger.error('插入命令失败:', error)
  }
}

// 插入颜色数字
const insertColorNumber = (colorNumber) => {
  try {
    // 防止快速点击（防抖）
    const now = Date.now()
    if (now - lastClickTime.value < 100) {
      return
    }
    lastClickTime.value = now
    
    logger.log('🎨 开始插入颜色数字:', colorNumber)
    
    // 尝试模拟键盘输入
    if (simulateKeyboardInput(colorNumber.toString())) {
      return
    }
    
    // 如果模拟键盘输入失败，使用简单的DOM方式
    logger.log('🔄 模拟键盘输入失败，使用简单DOM方式')
    insertTextAtCursor(colorNumber.toString())
    
  } catch (error) {
    logger.error('插入颜色数字失败:', error)
  }
}

// 隐藏命令面板（由管理器调用）
const hideCommandPanel = () => {
  // 更新响应式引用，触发视图更新
  isActiveEditorRef.value = false
  logger.log('📝 [CommandPanel] 隐藏命令面板')
}

// 显示命令面板（由管理器调用）
const showCommandPanelMethod = () => {
  // 更新响应式引用，触发视图更新
  isActiveEditorRef.value = true
  logger.log('📝 [CommandPanel] 显示命令面板')
}

// 创建编辑器实例对象，用于注册到管理器
const editorInstance = {
  hideCommandPanel,
  showCommandPanel: showCommandPanelMethod
}

// 命令面板折叠/展开
const toggleCommandPanel = () => {
  try {
    // 只有活动编辑器才能切换命令面板
    if (!commandPanelManager.isActiveEditor(editorInstance)) {
      logger.log('⚠️ 非活动编辑器，无法切换命令面板')
      return
    }
    logger.log('切换命令面板状态:', showCommandPanel.value, '->', !showCommandPanel.value)
    showCommandPanel.value = !showCommandPanel.value
  } catch (error) {
    logger.error('切换命令面板失败:', error)
  }
}

// 将 toggleCommandPanel 添加到 editorInstance
editorInstance.toggleCommandPanel = toggleCommandPanel

// 命令面板拖动处理
const handleToggleBtnMouseDown = (e) => {
  if (isRunning.value) return
  
  // 只允许通过按钮拖动，阻止按钮的默认点击行为在拖动时触发
  e.preventDefault()
  isDragging.value = true
  hasMoved.value = false
  dragStartX.value = e.clientX
  dragStartY.value = e.clientY
  
  // 获取命令面板当前位置
  if (commandPanelRef.value) {
    const rect = commandPanelRef.value.getBoundingClientRect()
    // 如果面板还没有设置过位置，保存初始位置
    if (buttonLeft.value === null || buttonTop.value === null) {
      buttonLeft.value = rect.left
      buttonTop.value = rect.top
    }
    // 使用当前保存的位置作为拖动起始位置（可能是已保存的位置或新获取的位置）
    initialButtonLeft.value = buttonLeft.value
    initialButtonTop.value = buttonTop.value
  }
  
  // 添加全局事件监听
  document.addEventListener('mousemove', handleToggleBtnMouseMove)
  document.addEventListener('mouseup', handleToggleBtnMouseUp)
}

const handleToggleBtnMouseMove = (e) => {
  if (!isDragging.value) return
  
  const deltaX = e.clientX - dragStartX.value
  const deltaY = e.clientY - dragStartY.value
  
  // 如果移动距离超过5px，认为是拖动而不是点击
  if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
    if (!hasMoved.value) {
      hasMoved.value = true
      // 标记为拖动状态，使用已在 mousedown 中设置的初始位置
    }
    
    // 基于初始位置计算新位置
    if (initialButtonLeft.value !== null && initialButtonTop.value !== null) {
      const newLeft = initialButtonLeft.value + deltaX
      const newTop = initialButtonTop.value + deltaY
      
      // 限制在视口内（考虑面板宽度）
      const panelWidth = showCommandPanel.value 
        ? (commandPanelRef.value?.offsetWidth || 350)
        : (commandPanelRef.value?.offsetWidth || 70)
      const panelHeight = commandPanelRef.value?.offsetHeight || 40
      
      const maxLeft = window.innerWidth - panelWidth
      const maxTop = window.innerHeight - panelHeight
      
      buttonLeft.value = Math.max(0, Math.min(newLeft, maxLeft))
      buttonTop.value = Math.max(0, Math.min(newTop, maxTop))
    }
  }
}

const handleToggleBtnMouseUp = (e) => {
  isDragging.value = false
  
  // 如果只是点击没有拖动，重置位置以保持原始布局
  if (!hasMoved.value) {
    buttonLeft.value = null
    buttonTop.value = null
  }
  
  // 重置初始位置
  initialButtonLeft.value = null
  initialButtonTop.value = null
  
  // 移除全局事件监听
  document.removeEventListener('mousemove', handleToggleBtnMouseMove)
  document.removeEventListener('mouseup', handleToggleBtnMouseUp)
}

const handleToggleBtnClick = (e) => {
  // 如果是拖动，不触发点击事件
  if (hasMoved.value) {
    e.preventDefault()
    e.stopPropagation()
    hasMoved.value = false
    return
  }
  
  // 正常点击，触发切换
  toggleCommandPanel()
}

// 使用响应式引用跟踪活动编辑器状态
const isActiveEditorRef = ref(false)

// 判断是否是活动编辑器（用于控制命令面板显示）
// 使用响应式引用而不是直接调用管理器，避免在计算属性中产生副作用
const isActiveEditor = computed(() => {
  // 读取响应式引用，这样当引用更新时会自动触发重新计算
  return isActiveEditorRef.value
})

// 命令面板样式计算属性
const commandPanelStyle = computed(() => {
  const baseStyle = {
    display: isActiveEditor.value ? '' : 'none' // 只有活动编辑器显示命令面板
  }
  
  if (buttonLeft.value !== null && buttonTop.value !== null) {
    return {
      ...baseStyle,
      position: 'fixed',
      left: `${buttonLeft.value}px`,
      top: `${buttonTop.value}px`,
      right: 'auto', // 移除原来的 right 定位，改用 left
      zIndex: 1000
    }
  }
  return baseStyle // 未拖动时使用 CSS 默认位置（top: 20px; right: 20px）
})

// 输入输出处理方法
const handleCinEnter = () => {
  if (isWaitingForInput.value && inputResolve.value) {
    const value = cinValue.value.trim()
    
    // 检查是否包含空格分隔的多个值
    if (value.includes(' ')) {
      // 按空格分割输入值
      const dataParts = value.split(/\s+/).filter(part => part.length > 0)
      if (dataParts.length > 0) {
        // 取第一个值作为当前输入
        const currentValue = dataParts.shift()
        // 将剩余值重新组合并保存到输入框
        cinValue.value = dataParts.join(' ')
        logger.log('处理空格分隔输入，当前值:', currentValue, '剩余值:', cinValue.value)
        inputResolve.value(currentValue)
        inputResolve.value = null
        isWaitingForInput.value = false
        return
      }
    }
    
    // 单个值或没有空格的情况，按原逻辑处理
    inputResolve.value(value)
    inputResolve.value = null
    isWaitingForInput.value = false
    cinValue.value = ''
  }
}

const handleCinEscape = () => {
  if (isWaitingForInput.value && inputResolve.value) {
    inputResolve.value('')
    inputResolve.value = null
    isWaitingForInput.value = false
    cinValue.value = ''
  }
}

const handlePenInputEnter = () => {
  if (inputResolve.value) {
    const value = penInputValue.value.trim()
    inputResolve.value(value)
    inputResolve.value = null
    showPenInput.value = false
    penInputValue.value = ''
  }
}

const handlePenInputEscape = () => {
  if (inputResolve.value) {
    inputResolve.value('')
    inputResolve.value = null
    showPenInput.value = false
    penInputValue.value = ''
  }
}

// 等待输入的方法
const waitForInput = (usePenInput = false) => {
  return new Promise((resolve) => {
    inputResolve.value = resolve
    
    // 根据当前输入模式决定使用哪种输入方式
    const shouldUsePenInput = usePenInput && inputMode.value === 'pen'
    
    if (shouldUsePenInput) {
      showPenInput.value = true
      isWaitingForInput.value = true
      // 计算笔附近的位置
      updatePenInputPosition()
      nextTick(() => {
        if (penInput.value) {
          penInput.value.focus()
        }
      })
    } else if (inputMode.value === 'window') {
      // 窗口输入模式：从cinWin输入框读取数据
      const inputText = cinValue.value.trim()
      logger.log('窗口输入模式，当前输入数据:', inputText)
      if (inputText) {
        // 解析输入数据（按空格或换行分割）
        const dataParts = inputText.split(/\s+/).filter(part => part.length > 0)
        logger.log('解析的数据部分:', dataParts)
        if (dataParts.length > 0) {
          const value = dataParts.shift() // 取第一个数据
          // 更新剩余数据
          cinValue.value = dataParts.join(' ')
          logger.log('返回数据:', value, '剩余数据:', cinValue.value)
          resolve(value)
          return
        }
      }
      // 如果没有数据，设置等待状态并聚焦到输入框
      logger.log('cinWin输入框为空，等待用户输入')
      isWaitingForInput.value = true
      nextTick(() => {
        if (cinInput.value) {
          cinInput.value.focus()
          cinInput.value.scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      })
    } else {
      // 默认模式：使用cinWin输入框
      const inputText = cinValue.value.trim()
      if (inputText) {
        // 解析输入数据（按空格或换行分割）
        const dataParts = inputText.split(/\s+/).filter(part => part.length > 0)
        if (dataParts.length > 0) {
          const value = dataParts.shift() // 取第一个数据
          // 更新剩余数据
          cinValue.value = dataParts.join(' ')
          resolve(value)
          return
        }
      }
      // 如果没有数据，设置等待状态并聚焦到输入框
      logger.log('cinWin输入框为空，等待用户输入')
      isWaitingForInput.value = true
      nextTick(() => {
        if (cinInput.value) {
          cinInput.value.focus()
          cinInput.value.scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      })
    }
  })
}

// 更新笔输入框位置
const updatePenInputPosition = () => {
  const canvasRect = drawCanvas.value?.getBoundingClientRect()
  if (canvasRect) {
    const x = toCanvasX(penState.value.x)
    const y = toCanvasY(penState.value.y)
    penInputStyle.value = {
      left: `${canvasRect.left + x + 20}px`,
      top: `${canvasRect.top + y - 10}px`,
      position: 'fixed',
      zIndex: 1001
    }
  }
}

// 输出到coutWin
const outputToCout = (value) => {
  // 直接追加输出，不自动添加换行符
  // 换行符由interpreter中的endl处理
  coutValue.value += String(value)
  // 自动滚动到底部
  nextTick(() => {
    if (coutOutput.value) {
      coutOutput.value.scrollTop = coutOutput.value.scrollHeight
    }
  })
}

// 设置输入模式
const setInputMode = (mode) => {
  inputMode.value = mode
  logger.log(`输入模式设置为: ${mode}`)
  
  // 如果是窗口模式且输入框为空，提供示例数据提示
  if (mode === 'window' && !cinValue.value.trim()) {
    // 不自动填入数据，而是提示用户输入
    logger.log('请在cinWin输入框中输入数据（如：100 50）')
  }
}




watch(() => props.readOnly, (newValue) => {
  if (editor.value) {
    editor.value.updateOptions({ readOnly: newValue })
  }
})

watch(() => props.theme, (newValue) => {
  setTheme(newValue)
})

// 监听value变化 - 优化版本
watch(() => props.value, (newValue) => {
  if (editor.value && newValue !== editorContent.value) {
    const value = newValue || ''
    editor.value.setValue(value)
    editorContent.value = value
    isContentDirty.value = false
  }
}, { immediate: false })

// 生命周期
onMounted(async () => {
  logger.log('🚀 GocEditor组件开始挂载...')
  
  // 添加 ResizeObserver 错误处理
  const originalErrorHandler = window.onerror
  window.onerror = (message, source, lineno, colno, error) => {
    if (message && message.includes('ResizeObserver loop completed with undelivered notifications')) {
      logger.warn('⚠️ ResizeObserver 错误已被捕获并忽略:', message)
      return true // 阻止错误冒泡
    }
    // 其他错误继续使用原来的处理方式
    if (originalErrorHandler) {
      return originalErrorHandler(message, source, lineno, colno, error)
    }
    return false
  }
  
  await nextTick()
  logger.log('✅ nextTick完成')
  
  logger.log('🎨 开始初始化Monaco...')
  await initMonaco()
  logger.log('✅ Monaco初始化完成')
  
  logger.log('🖼️ 开始初始化画布...')
  // 延迟初始化画布，确保DOM完全渲染
  canvasInitTimer = setTimeout(() => {
    initCanvas()
    logger.log('✅ 画布初始化完成')
  }, 50)
  
  // 初始化输入输出状态
  logger.log('📝 初始化输入输出状态...')
  inputMode.value = 'window' // 默认使用窗口输入模式
  logger.log('✅ 输入模式设置为:', inputMode.value)
  
  // 初始化速度设置
  logger.log('⚡ 初始化速度设置...')
  window.__gocSpeedLevel = props.defaults.speed
  logger.log('✅ 速度等级设置为:', props.defaults.speed)
  
  // 初始化字体大小设置
  logger.log('🔤 初始化字体大小设置...')
  const savedFontSize = localStorage.getItem('goc-editor-font-size')
  if (savedFontSize) {
    const parsedSize = parseInt(savedFontSize)
    if (parsedSize >= MIN_FONT_SIZE && parsedSize <= MAX_FONT_SIZE) {
      fontSize.value = parsedSize
      logger.log('✅ 从本地存储加载字体大小:', fontSize.value)
    }
  }
  logger.log('✅ 字体大小设置为:', fontSize.value)
  
  // 延迟居中显示画布，确保DOM已渲染
  centerViewTimer = setTimeout(() => {
    centerView()
  }, 100)
  
  // 添加窗口大小变化监听器
  handleResize = () => {
    if (editor.value) {
      setTimeout(() => {
        editor.value.layout()
      }, 100)
    }
  }
  
  window.addEventListener('resize', handleResize)
  
  // 使用安全的 ResizeObserver 监听编辑器容器大小变化
  if (editorContainer.value) {
    const layoutAdjuster = createDebouncedLayoutAdjuster(editor.value, 50)
    resizeObserver = createSafeResizeObserver((entries) => {
      for (let entry of entries) {
        layoutAdjuster()
      }
    })
    
    if (resizeObserver) {
      resizeObserver.observe(editorContainer.value)
      logger.log('✅ ResizeObserver 已设置')
    }
  }
  
  logger.log('🎉 GocEditor组件挂载完成!')
  logger.log('📋 命令面板状态:', showCommandPanel.value)
  
  // 注册编辑器到命令面板管理器
  const shouldShowPanel = commandPanelManager.registerEditor(editorInstance)
  logger.log('📝 [CommandPanel] 编辑器已注册，是否显示命令面板:', shouldShowPanel)
  
  // 更新响应式引用，触发计算属性重新计算
  isActiveEditorRef.value = shouldShowPanel
  
  // 根据管理器决定是否显示命令面板
  // 注意：实际的显示/隐藏由 commandPanelStyle 计算属性自动控制
  if (shouldShowPanel) {
    logger.log('✅ [CommandPanel] 这是第一个编辑器，命令面板将显示')
  } else {
    logger.log('⚠️ [CommandPanel] 已有其他编辑器，命令面板将隐藏')
  }
})

onUnmounted(() => {
  logger.log('🧹 [GocEditor] 开始清理组件资源...')
  
  try {
    // 从命令面板管理器注销编辑器
    logger.log('🧹 [GocEditor] 注销编辑器...')
    commandPanelManager.unregisterEditor(editorInstance)
    
    // 恢复原来的错误处理器
    logger.log('🧹 [GocEditor] 恢复错误处理器...')
    window.onerror = null
    
    // 清理窗口大小变化监听器
    logger.log('🧹 [GocEditor] 清理窗口监听器...')
    if (handleResize) {
      window.removeEventListener('resize', handleResize)
      handleResize = null
    }
    
    // 清理拖动事件监听器
    logger.log('🧹 [GocEditor] 清理拖动事件监听器...')
    document.removeEventListener('mousemove', handleToggleBtnMouseMove)
    document.removeEventListener('mouseup', handleToggleBtnMouseUp)
    
    // 清理 ResizeObserver
    if (resizeObserver) {
      resizeObserver.disconnect()
      resizeObserver = null
      logger.log('✅ [GocEditor] ResizeObserver 清理完成')
    }
    
    // 清理所有定时器
    logger.log('🧹 [GocEditor] 清理定时器...')
    if (editorReadyTimer) {
      clearTimeout(editorReadyTimer)
      editorReadyTimer = null
    }
    if (canvasInitTimer) {
      clearTimeout(canvasInitTimer)
      canvasInitTimer = null
    }
    if (centerViewTimer) {
      clearTimeout(centerViewTimer)
      centerViewTimer = null
    }
    if (contentChangeTimeout) {
      clearTimeout(contentChangeTimeout)
      contentChangeTimeout = null
    }
    logger.log('✅ [GocEditor] 定时器清理完成')
    
    // 清理内容缓存
    logger.log('🧹 [GocEditor] 清理内容缓存...')
    editorContent.value = ''
    isContentDirty.value = false
    logger.log('✅ [GocEditor] 内容缓存清理完成')
    
    // 停止动画（添加超时保护）
    logger.log('🧹 [GocEditor] 停止动画...')
    if (performance.value) {
      try {
        performance.value.stopAnimation()
        logger.log('✅ [GocEditor] 动画停止完成')
      } catch (error) {
        logger.warn('⚠️ [GocEditor] 停止动画时出错:', error)
      }
      
      try {
        performance.value.cleanup()
        logger.log('✅ [GocEditor] 性能优化器清理完成')
      } catch (error) {
        logger.warn('⚠️ [GocEditor] 性能优化器清理时出错:', error)
      }
    }
    
    // 清理Monaco编辑器（添加超时保护）
    logger.log('🧹 [GocEditor] 清理Monaco编辑器...')
    if (editor.value) {
      try {
        editor.value.dispose()
        editor.value = null
        logger.log('✅ [GocEditor] Monaco编辑器清理完成')
      } catch (error) {
        logger.warn('⚠️ [GocEditor] Monaco编辑器清理时出错:', error)
        editor.value = null
      }
    }
    
    // 清理Canvas上下文
    logger.log('🧹 [GocEditor] 清理Canvas上下文...')
    if (drawCtxRef.value) {
      drawCtxRef.value = null
    }
    logger.log('✅ [GocEditor] Canvas上下文清理完成')
    
    // 清理全局变量
    logger.log('🧹 [GocEditor] 清理全局变量...')
    try {
      delete window.__gocUpdatePen
      delete window.__gocSetPenVisible
    } catch (error) {
      logger.warn('⚠️ [GocEditor] 清理全局变量时出错:', error)
    }
    logger.log('✅ [GocEditor] 全局变量清理完成')
    
    // 清理其他引用
    logger.log('🧹 [GocEditor] 清理其他引用...')
    isRunning.value = false
    penVisible.value = false
    logger.log('✅ [GocEditor] 其他引用清理完成')
    
    logger.log('✅ [GocEditor] 组件资源清理完成')
  } catch (error) {
    logger.error('❌ [GocEditor] 清理过程中发生错误:', error)
    // 即使出错也要继续清理
    try {
      delete window.__gocUpdatePen
      delete window.__gocSetPenVisible
    } catch (e) {
      // 忽略清理错误
    }
  }
})

// 暴露 API
defineExpose({
  run,
  stop,
  clear,
  getCode,
  setCode,
  setTheme,
  getTrace,
  getCanvasImage,
  exportTrace,
  replay,
  getCursorPosition,
  setCursorPosition,
  insertTextAtCursor,
  insertCommand,
  insertColorNumber,
  toggleCommandPanel,
  centerView,
  increaseFontSize,
  decreaseFontSize,
  updateEditorFontSize
})
</script>

<style scoped>
.goc-editor {
  display: flex;
  flex-direction: column;
  border: 1px solid #e1e4e8;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  height: 900px; /* 设置固定高度，与顶部导航栏协调 */
}

.toolbar {
  display: flex;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid #e1e4e8;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  align-items: center;
}

.toolbar button {
  padding: 10px 20px;
  border: 1px solid #d1d5db;
  background: #fff;
  cursor: pointer;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 500;
  color: #374151;
  transition: all 0.2s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.toolbar button:hover {
  background: #f3f4f6;
  border-color: #9ca3af;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.toolbar button:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.toolbar button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.toolbar select {
  padding: 10px 16px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background: #fff;
  font-size: 16px;
  color: #374151;
  cursor: pointer;
  transition: all 0.2s ease;
}

.toolbar select:hover {
  border-color: #9ca3af;
}

.toolbar select:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

/* 字体控制按钮样式 */
.font-controls {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.font-btn {
  width: 32px;
  height: 32px;
  border: 1px solid #404040;
  background: #2d2d2d;
  color: #e5e5e5;
  cursor: pointer;
  border-radius: 4px;
  font-size: 18px;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  padding: 0;
  min-width: 32px;
}

.font-btn:hover:not(:disabled) {
  background: #404040;
  border-color: #666;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.font-btn:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.font-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.editor-container {
  display: flex;
  flex: 1;
  min-height: 0;
  background: #fff;
  height: 850px; /* 再次扩大高度到850px */
  position: relative; /* 为命令面板提供定位上下文 */
}

.canvas-area {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #00bcd4 0%, #0097a7 100%);
  border-right: 1px solid #e1e4e8;
  padding: 16px;
  min-width: 0; /* 允许flex收缩 */
}

.canvas-scroll-container {
  width: 100%;
  height: 100%;
  overflow: auto;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  background: #fff;
}

.canvas-wrap {
  position: relative;
  width: 900px;   /* 对应坐标范围 -400 到 400 */
  height: 900px;  /* 对应坐标范围 -400 到 400 */
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}

.canvas-wrap canvas {
  position: absolute;
  left: 0;
  top: 0;
  border: none;
  border-radius: 8px;
}

.canvas-wrap canvas:nth-child(1) {
  z-index: 0; /* 坐标轴Canvas - 最底层 */
}

.canvas-wrap canvas:nth-child(2) {
  z-index: 1; /* 绘制Canvas - 中间层 */
}

.canvas-wrap canvas:nth-child(3) {
  z-index: 2; /* 笔头Canvas - 最顶层 */
  pointer-events: none;
}

/* 自定义滚动条样式 */
.canvas-scroll-container::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

.canvas-scroll-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 6px;
}

.canvas-scroll-container::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 6px;
  border: 2px solid #f1f1f1;
}

.canvas-scroll-container::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.canvas-scroll-container::-webkit-scrollbar-corner {
  background: #f1f1f1;
}

.monaco-area {
  flex: 1;
  min-width: 0;
  background: #1e1e1e;
  border-radius: 0 0 8px 0;
  display: flex;
  flex-direction: column;
}

/* 编辑器控制按钮样式 */
.editor-controls {
  display: flex;
  gap: 8px;
  padding: 8px 12px;
  background: #2d2d2d;
  border-bottom: 1px solid #404040;
  border-radius: 8px 8px 0 0;
}

.editor-controls .run-btn,
.editor-controls .stop-btn {
  padding: 8px 16px;
  border: 1px solid #404040;
  background: #2d2d2d;
  color: #e5e5e5;
  cursor: pointer;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s ease;
  min-width: 60px;
}

.editor-controls .run-btn {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  border-color: #059669;
  color: white;
}

.editor-controls .run-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, #059669 0%, #047857 100%);
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(16, 185, 129, 0.3);
}

.editor-controls .stop-btn {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  border-color: #dc2626;
  color: white;
}

.editor-controls .stop-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(239, 68, 68, 0.3);
}

.editor-controls .run-btn:disabled,
.editor-controls .stop-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.monaco-container {
  width: 100%;
  height: 100%;
  flex: 1;
  border-radius: 0 0 8px 0;
}

/* 成功提示样式 - 在画布上显示 */
.success-notification {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2000;
  animation: successSlideIn 0.5s ease-out;
}

.success-content {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  color: white;
  padding: 20px 30px;
  border-radius: 12px;
  box-shadow: 0 10px 25px rgba(16, 185, 129, 0.3);
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  font-weight: 600;
  min-width: 200px;
  justify-content: center;
}

.success-icon {
  font-size: 24px;
  font-weight: bold;
  animation: successPulse 1s ease-in-out infinite;
}

.success-text {
  font-size: 16px;
  font-weight: 600;
}

@keyframes successSlideIn {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.8);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}

@keyframes successPulse {
  0%, 100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
}

/* 错误提示样式 - 固定在屏幕顶部显示 */
.error-notification {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2000;
  max-width: 600px;
  width: 90%;
  animation: errorSlideDown 0.3s ease-out;
}

.error-content {
  background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
  border: 2px solid #fecaca;
  border-radius: 8px;
  padding: 16px 20px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  box-shadow: 0 4px 12px rgba(220, 38, 38, 0.15);
  backdrop-filter: blur(10px);
}

.error-icon {
  color: #dc2626;
  font-size: 20px;
  font-weight: bold;
  flex-shrink: 0;
  margin-top: 2px;
}

.error-details {
  flex: 1;
}

.error-text {
  color: #dc2626;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 4px;
}

.error-suggestion {
  color: #991b1b;
  font-size: 13px;
  font-style: italic;
  opacity: 0.9;
}

.error-close-btn {
  background: none;
  border: none;
  color: #dc2626;
  font-size: 24px;
  font-weight: bold;
  cursor: pointer;
  padding: 0;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: all 0.2s ease;
  flex-shrink: 0;
  margin-left: 8px;
}

.error-close-btn:hover {
  background: rgba(220, 38, 38, 0.1);
  transform: scale(1.1);
}

.error-close-btn:active {
  transform: scale(0.95);
}

@keyframes errorSlideDown {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
}

/* 命令面板样式 - 移到编辑器外面 */
.command-panel {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 350px;
  padding: 20px;
  background: #f8f9fa;
  border: 2px solid #3498db;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  max-height: 700px;
  overflow-y: auto;
  transition: all 0.3s ease-in-out;
  z-index: 1000;
}

.command-panel-collapsed {
  width: 70px;
  padding: 10px;
  max-height: none;
  overflow: visible;
  border: 2px solid #3498db; /* 折叠状态也保持边框 */
}

.command-toggle {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 10px;
  position: relative;
}

.command-panel-collapsed .command-toggle {
  justify-content: center;
  margin-bottom: 0;
}

.toggle-btn {
  background: #3498db;
  border: 1px solid #2980b9;
  border-radius: 6px;
  padding: 8px 12px;
  cursor: move;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: white;
  transition: all 0.2s ease;
  box-shadow: 0 2px 4px rgba(52, 152, 219, 0.2);
  user-select: none;
}

.command-panel-collapsed .toggle-btn {
  padding: 10px;
  border-radius: 50%;
  justify-content: center;
  width: 40px;
  height: 40px;
}

/* 拖动时命令面板的样式由 commandPanelStyle 控制 */

.toggle-btn:hover:not(:disabled) {
  background: #2980b9;
  border-color: #21618c;
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(52, 152, 219, 0.3);
}

.toggle-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(52, 152, 219, 0.2);
}

.toggle-icon {
  font-size: 16px;
  font-weight: bold;
}

.toggle-text {
  font-weight: 600;
  white-space: nowrap;
}

.command-content {
  animation: fadeIn 0.3s ease-in-out;
  will-change: opacity, transform;
  contain: layout style paint;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateX(10px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.command-content h4 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #2c3e50;
  border-bottom: 2px solid #3498db;
  padding-bottom: 10px;
  font-size: 18px;
  font-weight: bold;
}

.command-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 14px;
  clear: both;
  margin-top: 20px;
  background: #ffffff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  border: 1px solid #e1e5e9;
}

.command-table th,
.command-table td {
  padding: 14px 18px;
  text-align: left;
  border-bottom: 1px solid #f1f3f4;
  transition: all 0.2s ease;
}

.command-table th {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  font-weight: 600;
  color: #ffffff;
  font-size: 15px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  letter-spacing: 0.5px;
}

/* 分类标题样式 */
.command-table tbody th {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
  color: #ffffff;
  font-size: 13px;
  font-weight: 600;
  padding: 10px 18px;
  text-align: center;
  border-bottom: 2px solid #e1e5e9;
  position: relative;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.command-table tbody th::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: linear-gradient(135deg, #ff6b6b 0%, #ffa500 100%);
}

.command-table td:first-child {
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  background: #f8fafc;
  cursor: pointer;
  user-select: none;
  font-weight: 500;
  color: #2d3748;
  border-right: 1px solid #e2e8f0;
  position: relative;
  min-width: 120px;
}

.command-table td:first-child::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: transparent;
  transition: all 0.2s ease;
}

.command-table td:first-child:hover {
  background: #e2e8f0;
  color: #1a202c;
  transform: translateX(2px);
}

.command-table td:first-child:hover::before {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.command-table td:last-child {
  color: #4a5568;
  font-weight: 400;
  background: #ffffff;
}

.command-table tr:hover {
  background: #f7fafc;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.command-table tr:hover td:first-child {
  background: #e2e8f0;
}

.command-table tr:hover td:last-child {
  background: #f7fafc;
}

/* 分类之间的分隔 */
.command-table tbody tr:has(th) {
  margin-top: 8px;
}

.command-table tbody tr:has(th) + tr td {
  border-top: 2px solid #e2e8f0;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .command-table {
    font-size: 13px;
  }
  
  .command-table th,
  .command-table td {
    padding: 10px 12px;
  }
  
  .command-table tbody th {
    font-size: 12px;
    padding: 8px 12px;
  }
}

/* 颜色面板样式 - 独立区域 */
.color-panel {
  width: 120px;
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  padding: 12px;
  margin-bottom: 20px;
  float: left;
  margin-right: 20px;
}

.color-panel h5 {
  margin: 0 0 10px 0;
  font-size: 14px;
  font-weight: 600;
  color: #495057;
  text-align: center;
}

.color-palette {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  width: 100%;
}

.color-item {
  width: 20px;
  height: 20px;
  border: 1px solid #ccc;
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.2s ease;
  color: #000;
  text-shadow: 0 0 1px rgba(255, 255, 255, 0.8);
  user-select: none;
}

.color-item:hover {
  transform: scale(1.1);
  border-color: #3498db;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  z-index: 10;
  position: relative;
}

.color-item:active {
  transform: scale(0.95);
}

/* 为浅色背景的颜色项添加深色文字 */
.color-item[style*="background-color: #FFFF00"],
.color-item[style*="background-color: #00FFFF"],
.color-item[style*="background-color: #FFC0CB"],
.color-item[style*="background-color: #C0C0C0"],
.color-item[style*="background-color: #FFD700"],
.color-item[style*="background-color: #FFFFFF"] {
  color: #000;
  text-shadow: 0 0 1px rgba(0, 0, 0, 0.8);
}

/* 命令按钮禁用状态样式 */
.command-content td.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: #f5f5f5;
  color: #999;
}

.command-content td.disabled:hover {
  background-color: #f5f5f5;
  color: #999;
}

/* 工具栏按钮禁用状态样式 */
.toolbar button:disabled,
.toolbar select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: #f5f5f5;
  color: #999;
}

.toolbar button:disabled:hover,
.toolbar select:disabled:hover {
  background-color: #f5f5f5;
  color: #999;
}

/* 字体控制按钮禁用状态样式 */
.font-controls button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: #f5f5f5;
  color: #999;
}

.font-controls button:disabled:hover {
  background-color: #f5f5f5;
  color: #999;
}

/* 命令面板切换按钮禁用状态样式 */
.toggle-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: #f5f5f5;
  color: #999;
}

.toggle-btn:disabled:hover {
  background-color: #f5f5f5;
  color: #999;
}

/* 命令面板滚动条样式 */
.command-panel::-webkit-scrollbar {
  width: 6px;
}

.command-panel::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.command-panel::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.command-panel::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .error-notification {
    top: 10px;
    width: 95%;
    max-width: none;
  }
  
  .error-content {
    padding: 12px 16px;
  }
  
  .error-text {
    font-size: 13px;
  }
  
  .error-suggestion {
    font-size: 12px;
  }
  
  .editor-container {
    flex-direction: column;
    height: auto;
    min-height: 600px;
  }
  
  .canvas-area {
    border-right: none;
    border-bottom: 1px solid #e1e4e8;
    padding: 16px;
    height: 300px;
    flex: none;
  }
  
  .canvas-scroll-container {
    width: 100%;
    height: 100%;
  }
  
  .canvas-wrap {
    width: 1400px;  /* 移动端再次扩大尺寸 */
    height: 1400px; /* 移动端再次扩大尺寸 */
  }
  
  .monaco-area {
    border-radius: 0 0 8px 8px;
    flex: 1;
    min-height: 300px;
  }
  
  .monaco-container {
    border-radius: 0 0 8px 8px;
    min-height: 300px;
  }
  
  .toolbar {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 12px;
  }
  
  .toolbar button {
    padding: 6px 12px;
    font-size: 13px;
  }
}

/* 输入输出面板样式 */
.io-panel {
  display: flex;
  gap: 20px;
  padding: 20px;
  background: #f8f9fa;
  border-top: 1px solid #e1e4e8;
  border-radius: 0 0 8px 8px;
}

.io-box {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.io-label {
  font-size: 16px;
  font-weight: 600;
  color: #3498db;
  margin: 0;
}

.io-input-container,
.io-output-container {
  position: relative;
}

.io-input {
  width: 100%;
  height: 50px;
  padding: 12px 16px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background: #fff;
  font-size: 16px;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  transition: all 0.2s ease;
  resize: none;
}

.io-input:focus {
  outline: none;
  border-color: #3498db;
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}

.io-input:disabled {
  background: #f3f4f6;
  color: #9ca3af;
  cursor: not-allowed;
}

.io-input.waiting-for-input {
  border-color: #f59e0b;
  box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
  animation: waiting-pulse 1.5s ease-in-out infinite;
}

@keyframes waiting-pulse {
  0%, 100% {
    border-color: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
  }
  50% {
    border-color: #d97706;
    box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.2);
  }
}

.input-hint {
  font-size: 14px;
  color: #6b7280;
  margin-top: 6px;
  padding: 6px 12px;
  background: #f9fafb;
  border-radius: 4px;
  border-left: 3px solid #3498db;
}

.io-output {
  width: 100%;
  height: 100px;
  padding: 12px 16px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background: #f3f4f6;
  font-size: 16px;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  color: #374151;
  overflow-y: auto;
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* 笔附近输入框样式 */
.pen-input-overlay {
  position: fixed;
  z-index: 1001;
  pointer-events: auto;
}

.pen-input-box {
  background: #fff;
  border: 2px solid #3498db;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  padding: 4px;
}

.pen-input {
  width: 120px;
  height: 32px;
  padding: 4px 8px;
  border: none;
  border-radius: 4px;
  background: #fff;
  font-size: 12px;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  outline: none;
}

.pen-input:focus {
  background: #f8f9fa;
}

/* 深色模式支持 */
@media (prefers-color-scheme: dark) {
  .goc-editor {
    background: #1e1e1e;
    border-color: #404040;
  }
  
  .toolbar {
    background: linear-gradient(135deg, #2d2d2d 0%, #404040 100%);
    border-color: #404040;
  }
  
  .toolbar button {
    background: #2d2d2d;
    border-color: #404040;
    color: #e5e5e5;
  }
  
  .toolbar button:hover {
    background: #404040;
    border-color: #666;
  }
  
  .toolbar select {
    background: #2d2d2d;
    border-color: #404040;
    color: #e5e5e5;
  }
  
  .canvas-area {
    background: linear-gradient(135deg, #1a2a3a 0%, #2d4a5a 100%);
    border-color: #404040;
  }
  
  .canvas-wrap {
    background: #1e1e1e;
  }
  
  .io-panel {
    background: #2d2d2d;
    border-color: #404040;
  }
  
  .io-label {
    color: #60a5fa;
  }
  
  .io-input {
    background: #1e1e1e;
    border-color: #404040;
    color: #e5e5e5;
  }
  
  .io-input:focus {
    border-color: #60a5fa;
    box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.1);
  }
  
  .io-input:disabled {
    background: #374151;
    color: #9ca3af;
  }
  
  .io-input.waiting-for-input {
    border-color: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
  }
  
  .io-output {
    background: #374151;
    border-color: #404040;
    color: #e5e5e5;
  }
  
  .pen-input-box {
    background: #1e1e1e;
    border-color: #60a5fa;
  }
  
  .pen-input {
    background: #1e1e1e;
    color: #e5e5e5;
  }
  
  .pen-input:focus {
    background: #374151;
  }
  
  .input-hint {
    background: #374151;
    color: #d1d5db;
    border-left-color: #60a5fa;
  }
}
</style>
